﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;

namespace System.Map
{
    public class LatLngHelper
    {
        ///// <summary>
        ///// 计算两点之间的距离
        ///// </summary>
        ///// <param name="aMapLng"></param>
        ///// <param name="aMapLat"></param>
        ///// <param name="bMapLng"></param>
        ///// <param name="bMapLat"></param>
        ///// <returns></returns>
        //public static int Distance(decimal aMapLng, decimal aMapLat, decimal bMapLng, decimal bMapLat)
        //{
        //    if (aMapLng == 0 || aMapLat == 0 || bMapLng == 0 || bMapLat == 0)
        //    {
        //        return Int32.MaxValue;
        //    }
        //    double aRadLat = Convert.ToDouble(aMapLat) * Math.PI / 180;
        //    double bRadLat = Convert.ToDouble(bMapLat) * Math.PI / 180;
        //    double abRadLat = aRadLat - bRadLat;
        //    double abRadLng = Convert.ToDouble(aMapLng) * Math.PI / 180 - Convert.ToDouble(bMapLng) * Math.PI / 180;
        //    double distanceRate = 2 * Math.Asin(Math.Sqrt(Math.Pow(Math.Sin(abRadLat / 2), 2) + Math.Cos(aRadLat) * Math.Cos(bRadLat) * Math.Pow(Math.Sin(abRadLng / 2), 2)));
        //    return Convert.ToInt32(distanceRate * 6378137);
        //}
        private static double Rad(double d)
        {
            return d * Math.PI / 180.0;
        }

        #region Baidu Location Calculate Distance Test OK 

        private static int acount = 0;
        public static double Distance(double aMapLng, double aMapLat, double bMapLng, double bMapLat)
        {
            acount ++;
            Debug.Write(acount);
            var locationA = new Location() { Lat = aMapLat, Lng = aMapLng };
            var locationB = new Location() { Lat = bMapLat, Lng = bMapLng };
            return Math.Round(Distance(locationA, locationB));
        }
        /// <summary>
        /// Bmap计算两点之间的距离
        /// </summary>
        /// <param name="lacationA"></param>
        /// <param name="lacationB"></param>
        /// <returns></returns>
        public static double Distance(Location lacationA, Location lacationB)
        {
            return getDistanceByLL(lacationA, lacationB);
        }
        private static double getDistanceByLL(Location cN, Location cL)
        {
            cN.Lng = getLoop(cN.Lng, -180, 180);
            cN.Lat = getRange(cN.Lat, -74, 74);
            cL.Lng = getLoop(cL.Lng, -180, 180);
            cL.Lat = getRange(cL.Lat, -74, 74);
            var cJ = toRadians(cN.Lng);
            var cM = toRadians(cN.Lat);
            var T = toRadians(cL.Lng);
            var cK = toRadians(cL.Lat);
            return getDistance(cJ, T, cM, cK);
        }

        private const double EARTHRADIUS = 6370996.81;
        /// <summary>
        /// From Baidu Api javascript source code
        /// </summary>
        /// <param name="cJ"></param>
        /// <param name="T"></param>
        /// <param name="cL"></param>
        /// <param name="cK"></param>
        /// <returns></returns>
        private static double getDistance(double cJ, double T, double cL, double cK)
        {
            // return this.EARTHRADIUS*Math.acos((Math.sin(cL)*Math.sin(cK)+Math.cos(cL)*Math.cos(cK)*Math.cos(T-cJ)))
            return EARTHRADIUS * Math.Acos((Math.Sin(cL) * Math.Sin(cK) + Math.Cos(cL) * Math.Cos(cK) * Math.Cos(T - cJ)));
        }
        private static double toRadians(double T)
        {
            return Math.PI * T / 180;
        }
        private static double getRange(double cK, double cJ, double T)
        {
            cK = Math.Max(cK, cJ);
            cK = Math.Min(cK, T);
            return cK;
        }
        private static double getLoop(double cK, double cJ, double T)
        {
            while (cK > T)
            {
                cK -= T - cJ;
            }
            while (cK < cJ)
            {
                cK += T - cJ;
            }
            return cK;
        }
        #endregion

    }
    /// <summary>
    /// 高斯投影中所选用的参考椭球
    /// </summary>
    public enum GaussSphere
    {
        Beijing54,
        Xian80,
        WGS84,
    }
}